package com.uziot.bucket.dubbo.consumer.web;

import com.uziot.bucket.dubbo.service.AsyncTestService;
import com.uziot.bucket.dubbo.service.AsyncTestService2;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * @author shidt
 * @version V1.0
 * @className AsyncTestController
 * @date 2020-11-28 15:46:46
 * @description 模拟异步服务接口
 * 注意：Provider端异步执行和Consumer端异步调用是相互独立的，你可以任意正交组合两端配置
 * <p>
 * 案例来源开源项目：https://gitee.com/svenaugustus/springcloud-bucket?_from=gitee_search
 */
@RestController
@RequestMapping("/")
public class AsyncTestController {

    @DubboReference(group = "dev", version = "1.0.0")
    private AsyncTestService asyncService;

    @DubboReference(group = "dev", version = "1.0.0")
    private AsyncTestService2 asyncService2;

    @GetMapping("/asyncCall")
    public String asyncCall() throws ExecutionException, InterruptedException {
        // 调用直接返回CompletableFuture
        CompletableFuture<String> future = asyncService.sayHello("async1");
        // 增加回调
        future.whenComplete((value, exception) -> {
            if (exception != null) {
                exception.printStackTrace();
            } else {
                System.out.println("CompletableFuture接口，响应（CompletableFuture调用方式）: " + value);
            }
        });
        // 早于结果输出
        System.out.println("在响应返回之前执行");
        return future.get();
    }

    @GetMapping("/asyncCall2")
    public String asyncCall2() throws ExecutionException, InterruptedException {
        // 此调用会立即返回null
        asyncService2.sayHello("zeno");
        // 拿到调用的Future引用，当结果返回后，会被通知和设置到此Future
        CompletableFuture<String> future = RpcContext.getContext().getCompletableFuture();
        // 为Future添加回调
        future.whenComplete((value, exception) -> {
            if (exception != null) {
                exception.printStackTrace();
            } else {
                System.out.println("普通接口，响应（CompletableFuture调用方式）: " + value);
            }
        });
        return future.get();
    }

    @GetMapping("/asyncCall3")
    public String asyncCall3() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = RpcContext.getContext()
                .asyncCall(() -> asyncService2.sayHello("单向呼叫request1”"));
        return future.get();
    }

}
